﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Diagnostics;
using System.Windows.Forms;

using MonoDevelop.Core;
using MonoDevelop.Ide;

namespace Coq.MonoDevelop
{
    class InteractiveSession
    {
        string server = "MonoDevelop" + Guid.NewGuid().ToString("n");
        string args = "";
        
        //string path = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles),"Coq\\bin\\");
        //System.Reflection.Assembly.GetAssembly(typeof(InteractiveSession)).Location
        string path = Path.Combine((new FileInfo (System.Reflection.Assembly.GetAssembly(typeof(InteractiveSession)).Location)).DirectoryName, "Coq\\bin\\");

        private bool waitingForResponse = false;

        public event EventHandler Exited;
        public event textHandler TextRecieved;
        public event voidHandler PromptReady;
        public delegate void textHandler(string s);
        public delegate void voidHandler();

        Process coqProcess = null;
        Process CoqProcess
        {
            get
            {
                if (coqProcess != null)
                    return coqProcess;

                ProcessStartInfo psi = new ProcessStartInfo()
                {
                    FileName = path,
                    Arguments = args,
                    RedirectStandardError = true,
                    RedirectStandardInput = true,
                    RedirectStandardOutput = true,
                    UseShellExecute = false,
                    CreateNoWindow = true
                };

                try
                {
                    coqProcess = Process.Start(psi);
                }
                catch (Exception e)
                {
                    //maybe do sth else
                    throw e;
                }

                coqProcess.OutputDataReceived += new DataReceivedEventHandler(coqProcess_OutputDataReceived);
                coqProcess.ErrorDataReceived += new DataReceivedEventHandler(coqProcess_OutputDataReceived);
                coqProcess.Exited += Exited;

                return coqProcess;
            }
        }

        public InteractiveSession()
        {
            //Find Coq Executable
            if (!Directory.Exists(path))
                path = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.CommonProgramFiles),"Coq\\bin\\");

            if (!Directory.Exists(path))
                throw new FileNotFoundException("Coq folder not found");

            path = Path.Combine(path, "CoqTop.exe");

            if (!File.Exists(path))
                throw new FileNotFoundException("CoqTop.exe not found");
        }

        void coqProcess_OutputDataReceived(object sender, DataReceivedEventArgs e)
        {
            if (e.Data == null)
                return;

            if (e.Data.Trim().ToLower().StartsWith("coq <"))
                DispatchService.GuiDispatch(() => { PromptReady(); });
            else
                if (e.Data.Trim() != "")
                {
                    waitingForResponse = false;
                    DispatchService.GuiDispatch(() => { TextRecieved(e.Data); });
                }
        }

        public void StartRecieving()
        {
            CoqProcess.BeginOutputReadLine();
            CoqProcess.BeginErrorReadLine();
        }

        public void Kill()
        {
            CoqProcess.Kill();
            coqProcess = null;
        }

        public void SendCommand(string str) 
        {
            waitingForResponse = true;
            str += Environment.NewLine;

            CoqProcess.StandardInput.Write(str);
        }


    }
}
